package model.impl;

import java.util.List;

import org.hibernate.HibernateException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import DAO.HibernateUtil;
import DAO.PassengerDAO;
import DAO.impl.PassengerDAOImpl;
import DTO.DTOManager;
import DTO.PassengerDTO;
import model.impl.Passenger;

/**
 * Class that implements the model.Passenger interface.
 */
public class PassengerImpl implements model.Passenger {
	
	private PassengerDAO passengerDAO = new PassengerDAOImpl();

	private DTOManager dtoManager = new DTOManager();

	private Logger logger = LoggerFactory.getLogger("PassengerImpl");
	
	/**
	 * This method checks the DTO for uniqueness and if it's so, it adds a new 
	 * Passenger entity to DB with instances equal to the original DTO
	 * 
	 * @param passenger	- DTO of passenger which is required to be registered
	 * @return			- a new created Passenger entity or null if check
	 * 					  for uniqueness failed
	 */
	public Passenger registrationOfNewPassenger(PassengerDTO passenger) {
		Passenger tempPassenger = null;
		try {
			HibernateUtil.beginTransaction();
			if((this.passengerDAO.findPassengerByLogin(passenger
					.getLogin()) == null) && (this.passengerDAO
					.findPassengerByNameData(passenger.getPassengerName(), 
					passenger.getPassengerSurname(), 
					passenger.getPassengerDateOfBirth()) == null)) {
				tempPassenger = this.dtoManager.createNewPassengerFromDTO(passenger);
				this.passengerDAO.save(tempPassenger);
			}
			HibernateUtil.commitTransaction();
		} catch (HibernateException e) {
			this.logger.error("Error in registration of new passenger " 
					+ e.getLocalizedMessage());
			HibernateUtil.rollbackTransaction();
		} 
		return tempPassenger;
	}
	
	/**
	 * This method checks if there is a passenger in DB which has the same 
	 * ID as a received DTO and which is currently logged in. If it's found, 
	 * method return DTO object that represent all the instances of found 
	 * passenger entity.
	 * 
	 * @param passenger	- DTO of passenger which is required to be refreshed
	 * @return			- DTO that is associated with refreshed Passenger entity
	 * 					  or null in any other cases.
	 */
	public PassengerDTO refreshPassengerInfo (PassengerDTO passenger) {
		try {
			HibernateUtil.beginTransaction();
			Passenger pass = this.passengerDAO.findByID(Passenger.class,
					passenger.getPassengerID());	
			if (pass != null) {
				HibernateUtil.commitTransaction();
				return this.dtoManager.createPassengerDTO(pass);
			}
			HibernateUtil.commitTransaction();
		} catch (HibernateException e) {
			this.logger.error("Error in refresh passenger info " 
											+ e.getLocalizedMessage());
			HibernateUtil.rollbackTransaction();
		} 
		return null;
	}

	/**
	 * This method checks if there is a passenger in DB which has the same 
	 * login and password as a received DTO, and if it's so it logs in this
	 * passenger.
	 * 
	 * @param passenger - DTO of passenger which is required to be logged in
	 * @return			- DTO that is associated with found Passenger entity
	 * 					  or null if the search failed.
	 */
	public PassengerDTO loginOfExistingPassenger(PassengerDTO passenger) {
		try {
			HibernateUtil.beginTransaction();
			Passenger pass = this.passengerDAO.findPassengerByLoginPassword
					(passenger.getLogin(), passenger.getPassword());	
			if (pass != null) {
				HibernateUtil.commitTransaction();
				return this.dtoManager.createPassengerDTO(pass);
			}
			HibernateUtil.commitTransaction();
		} catch (HibernateException e) {
			this.logger.error("Error in login existing passenger " 
												+ e.getLocalizedMessage());
			HibernateUtil.rollbackTransaction();
		} 
		return null;
	}

	/**
	 * This method checks if there is a passenger in DB which has the same 
	 * ID as a received DTO. If a passenger entity is found in DB, method 
	 * removes it.
	 * 
	 * @param passengerDTO - DTO of passenger which is required to be removed
	 */
	public void removeUniquePassenger(PassengerDTO passengerDTO) {
		try {
			HibernateUtil.beginTransaction();
			Passenger passenger = this.passengerDAO.findByID(Passenger.class, 
					passengerDTO.getPassengerID());
			if (passenger != null) {
				this.passengerDAO.delete(passenger);
			}
			HibernateUtil.commitTransaction();
		} catch (HibernateException e) {
			this.logger.error("Error in remove of unique passenger " 
													+ e.getLocalizedMessage());
			HibernateUtil.rollbackTransaction();
		} 
		
	}

	/**
	 * This method checks if there is a passenger in DB which has the same 
	 * ID as the given DTO. If it is found in DB, method modify its instances
	 * according to the given DTO.
	 * 
	 * @param passengerDTO - DTO of passenger which is required to be modified
	 */
	public void modifyUniquePassenger(PassengerDTO passengerDTO) {
		try {
			HibernateUtil.beginTransaction();
			Passenger passenger = this.passengerDAO.findByID(Passenger.class, 
					passengerDTO.getPassengerID());
			if (passenger != null) {
				passenger.setLogin(passengerDTO.getLogin());
				passenger.setPassengerDateOfBirth(passengerDTO
						.getPassengerDateOfBirth());
				passenger.setPassengerName(passengerDTO.getPassengerName());
				passenger.setPassengerSurname(passengerDTO.getPassengerSurname());
				passenger.setPassword(passengerDTO.getPassword());
				this.passengerDAO.merge(passenger);
			}
			HibernateUtil.commitTransaction();
		} catch (HibernateException e) {
			this.logger.error("Error in modify unique passenger " 
													+ e.getLocalizedMessage());
			HibernateUtil.rollbackTransaction();
		} 
	}

	/**
	 * This method checks if there is a passenger in DB which has the same 
	 * login and password as a received DTO and which is currently logged in.
	 * If it's found, method logs it out.
	 * 
	 * @param passengerDTO - DTO of passenger which is required to be logged out
	 * @return			   - true if passenger was logged out or false in any
	 * 						 other cases
	 */
	@Override
	public boolean logOutOfExistingPassenger(PassengerDTO passengerDTO) {
		try {
			HibernateUtil.beginTransaction();
			Passenger passenger = this.passengerDAO.findPassengerByLogin
					(passengerDTO.getLogin());
			if (passenger != null) {
				HibernateUtil.commitTransaction();
				return true;
			}
			HibernateUtil.commitTransaction();
		} catch (HibernateException e) {
			this.logger.error("Error in logout of existing passenger " 
												+ e.getLocalizedMessage());
			HibernateUtil.rollbackTransaction();
		} 
		return false;
	}

	/**
	 * Method looks for all the Passenger entities in DB.
	 * @return	- List of all Passenger entities in DB or null if there is no
	 * 			  passengers in DB.
	 */
	@Override
	public List<Passenger> findAll() {
		List<Passenger> passengers = null;
		try {
			HibernateUtil.beginTransaction();
			passengers = this.passengerDAO.findAll(Passenger.class);
			HibernateUtil.commitTransaction();
		} catch (HibernateException e) {
			this.logger.error("Error in find all passengers " 
													+ e.getLocalizedMessage());
			HibernateUtil.rollbackTransaction();
		} 
		return passengers;
	}

	
	/**
	 * Looks for a Passenger with the passenger's instances equals to the 
	 * given parameters. It's as is PassengerDAO method wrapped with 
	 * transaction.
	 * 
	 * @param login	- Passenger.login
	 * @return		- Passenger entity object or null if such object was
	 * 				  not found
	 */
	@Override
	public model.impl.Passenger findPassengerByLogin(String login) {
		model.impl.Passenger passenger = null;
		try {
			HibernateUtil.beginTransaction();
			passenger = this.passengerDAO.findPassengerByLogin(login);
			HibernateUtil.commitTransaction();
		} catch (HibernateException e) {
			this.logger.error("Error in find passenger by login " 
													+ e.getLocalizedMessage());
			HibernateUtil.rollbackTransaction();
		} 
		return passenger;
	}
}
